/*
Copyright 2011 Johan Maasing

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package nu.zoom.catonine.prefs.gui.impl;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;

import nu.zoom.catonine.prefs.Preferences;
import nu.zoom.catonine.prefs.Preferences.WindowOpenMode;
import nu.zoom.catonine.prefs.gui.PreferencesGUI;
import nu.zoom.gal.error.ErrorReporter;
import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.common.BackendException;
import nu.zoom.swing.desktop.preferences.InvalidDataTypeException;
import nu.zoom.swing.field.IntegerField;
import nu.zoom.swing.layout.VerticalPanel;
import nu.zoom.ui.Resources;
import nu.zoom.ui.Resources.ResourceNotFoundException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
 * 
 */
public final class PreferencesGUIFactory implements PreferencesGUI {
	private final Log log = LogFactory.getLog(getClass());
	private final Workbench workbench;
	private final Resources resources;
	private final ErrorReporter errorReporter;
	private final Preferences preferences;
	private WindowModeItems[] items;

	public PreferencesGUIFactory(final Workbench workbench, final Resources resources,
			final ErrorReporter errorReporter, final Preferences preferences) {
		super();
		this.workbench = workbench;
		this.resources = resources;
		this.errorReporter = errorReporter;
		this.preferences = preferences;
	}

	@Override
	public WorkbenchFrame displayPreferences() {
		final VerticalPanel panel = new VerticalPanel();
		final WorkbenchFrame workbenchFrame =
				workbench.createWorkbenchFrame("svansprogram-preferences-window", panel, null, true, true);
		try {
			createWindowModeGUI(panel);
			creteScrollbackGUI(panel);

			workbenchFrame.setTitle(resources.getMessage("nu.zoom.catonine.preferences.menu"));
			workbenchFrame.setFrameIcon(resources.getIcon("nu.zoom.catonine.preferences.menu.icon"));
		} catch (Exception e) {
			errorReporter.reportError(e);
		}
		return workbenchFrame;
	}

	private void creteScrollbackGUI(VerticalPanel panel) throws ResourceNotFoundException, InvalidDataTypeException,
			BackendException {
		final JLabel sizeLabel = new JLabel(resources.getMessage("nu.zoom.catonine.preferences.scrollback.size"));
		final IntegerField sizeField = new IntegerField(sizeLabel, 4) {
			private static final long serialVersionUID = -6132838527180075831L;

			@Override
			protected void validationPassed() {
				super.validationPassed();
				try {
					Integer size = Integer.valueOf(getText());
					preferences.setScrollbackSize(size);
					log.debug("Saved scrollback size as: " + size);
				} catch (NumberFormatException e) {
					log.error(e);
				} catch (InvalidDataTypeException e) {
					log.error(e);
				} catch (BackendException e) {
					log.error(e);
				}
			}

		};
		Integer scrollbackSize = preferences.getScrollbackSize();
		sizeField.setText((scrollbackSize != null ? scrollbackSize.toString() : ""));
		sizeField.setToolTipText(resources.getMessage("nu.zoom.catonine.preferences.scrollback.size.tt"));
		sizeField.setEnabled(scrollbackSize != null);
		final JCheckBox enableLimitButton = new JCheckBox();
		enableLimitButton.setToolTipText(resources.getMessage("nu.zoom.catonine.preferences.scrollback.enable.tt"));
		enableLimitButton.setSelected(scrollbackSize != null);
		enableLimitButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					if (enableLimitButton.isSelected()) {
						log.debug("Enable scrollback limit");
						sizeField.setEnabled(true);
						Integer scrollbackSize = preferences.getScrollbackSize();
						sizeField.setText((scrollbackSize != null ? scrollbackSize.toString() : ""));
					} else {
						log.debug("Disable scrollback limit");
						sizeField.setEnabled(false);
						preferences.setScrollbackSize(null);
					}
				} catch (InvalidDataTypeException e1) {
					log.error(e1);
				} catch (BackendException e1) {
					log.error(e1);
				}
			}
		});
		panel.addRow(resources.getMessage("nu.zoom.catonine.preferences.scrollback.enable"), enableLimitButton);
		panel.addRow(sizeLabel, sizeField);
	}

	private void createWindowModeGUI(final VerticalPanel panel) throws ResourceNotFoundException,
			InvalidDataTypeException, BackendException {
		final JComboBox detachedControl = new JComboBox(getWindowItems());
		detachedControl.setEditable(false);
		detachedControl.addActionListener(new WindowModeActionListener(detachedControl));
		switch (this.preferences.getWindowOpenMode()) {
			case Attached:
				detachedControl.setSelectedItem(this.items[1]);
				break;
			case Detached:
				detachedControl.setSelectedItem(this.items[2]);
			default:
				break;
		}
		final JLabel wmodeLabel = new JLabel(resources.getMessage("nu.zoom.catonine.preferences.wmode"));
		wmodeLabel.setToolTipText(resources.getMessage("nu.zoom.catonine.preferences.wmode.tt"));
		panel.addRow(wmodeLabel, detachedControl);
	}

	private synchronized WindowModeItems[] getWindowItems() throws ResourceNotFoundException {
		if (this.items == null) {
			this.items = new WindowModeItems[3];
			this.items[0] =
					new WindowModeItems(WindowOpenMode.Rememeber,
							this.resources.getMessage("nu.zoom.catonine.preferences.wmode.rememeber.lm"));
			this.items[1] =
					new WindowModeItems(WindowOpenMode.Attached,
							this.resources.getMessage("nu.zoom.catonine.preferences.wmode.attached.lm"));
			this.items[2] =
					new WindowModeItems(WindowOpenMode.Detached,
							this.resources.getMessage("nu.zoom.catonine.preferences.wmode.detached.lm"));
		}
		return this.items;
	}

	/**
	 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
	 * 
	 */
	private final class WindowModeActionListener implements ActionListener {
		private final JComboBox detachedControl;

		/**
		 * @param detachedControl
		 */
		private WindowModeActionListener(JComboBox detachedControl) {
			this.detachedControl = detachedControl;
		}

		@Override
		public void actionPerformed(final ActionEvent event) {
			Object selectedItem = detachedControl.getSelectedItem();
			if ((selectedItem != null) && (selectedItem instanceof WindowModeItems)) {
				WindowOpenMode newMode = ((WindowModeItems) selectedItem).getMode();
				try {
					log.debug("Setting window open mode to: " + newMode);
					preferences.setWindowOpenMode(newMode);
				} catch (final Exception exc) {
					errorReporter.reportError(exc);
				}
			}
		}
	}

	static class WindowModeItems {
		final private WindowOpenMode mode;
		final private String message;

		public WindowModeItems(final WindowOpenMode mode, final String message) {
			super();
			this.mode = mode;
			this.message = message;
		}

		@Override
		public String toString() {
			return message;
		}

		WindowOpenMode getMode() {
			return mode;
		}

	}
}
